
package dao;

import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;


public abstract class AbstractFacade<T> {
    private Class<T> entityClass;

    /**
     * Constructeur
     * @param entityClass
     */
    public AbstractFacade(Class<T> entityClass) {
        this.entityClass = entityClass;
    }

    /**
     * Getter entity manager
     * @return entity manager
     */
    protected abstract EntityManager getEntityManager();

    /**
     * Méthode de création d'un objet d'un type
     * @param objet d'un type à créer
     */
    public void create(T entity) {
        getEntityManager().persist(entity);
    }

    /**
     * Méthode de modification d'un objet d'un type
     * @param entity à modifier
     * @return objet d'un type modifié
     */
    public T edit(T entity) {
        return getEntityManager().merge(entity);
    }

    /**
     * Méthode de suppression d'un objet d'un type
     * @param objet d'un type à supprimer
     */
    public void remove(T entity) {
        getEntityManager().remove(getEntityManager().merge(entity));
    }

    /**
     * Méthode pour extraire tous les objets d'un type à partir de l'id
     * @param id : id à trouver
     * @return objet d'un type trouvé
     */
    public T find(Object id) {
        return getEntityManager().find(entityClass, id);
    }

    /**
     * Méthode pour extraire tous les types
     * @return liste de tous les objets d'un type
     */
    public List<T> findAll() {
        CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
        cq.select(cq.from(entityClass));
        return getEntityManager().createQuery(cq).getResultList();
    }

    /**
     * Méthode pour extraire la liste de tous les objets d'un type en utilisant les indices
     * @param range : tableau d'indice
     * @return liste de tous les objets d'un type
     */
    public List<T> findRange(int[] range) {
        CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
        cq.select(cq.from(entityClass));
        Query q = getEntityManager().createQuery(cq);
        q.setMaxResults(range[1] - range[0]);
        q.setFirstResult(range[0]);
        return q.getResultList();
    }

    /**
     * Méthode pour compter le nombre d'objet d'un type
     * @return nombre trouvé
     */
    public int count() {
        CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
        Root rt = cq.from(entityClass);
        cq.select(getEntityManager().getCriteriaBuilder().count(rt));
        Query q = getEntityManager().createQuery(cq);
        return ((Long) q.getSingleResult()).intValue();
    }

}
